package rdb

import (
	"context"
	"fmt"
	"github.com/redis/go-redis/v9"
	"sync"
)

type SetList interface {
	TopicKey(id any) string
	RedisClient() *redis.Client
	IsExist(id any, key string) (bool, error)
	Add(id any, value string) error
	Adds(id any, keys []string) error
	Del(id any, key string) error
	Dels(id any, keys []string) error
	Spop(id any, limit uint) ([]string, error)
	SpopAll(id any) ([]string, error)
	GetRandKeys(id any, limit uint) ([]string, error)
	Count(id any) (int64, error)
	GetAllKey(id any) ([]string, error)
	ClearAll(id any) error
}

type _setList struct {
	Topic string        //主题
	Redis *redis.Client //Redis客户端
	RWL   sync.RWMutex  //读写锁
}

func NewSetList(client *redis.Client, topic string) SetList {
	return &_setList{
		Topic: topic,
		Redis: client,
		RWL:   sync.RWMutex{},
	}
}

// TopicKey 返回默认生成的主题key
func (sl *_setList) TopicKey(id any) string {
	return fmt.Sprint("SetList_", sl.Topic, "_", id)
}

// RedisClient 返回绑定的Redis客户端
func (sl *_setList) RedisClient() *redis.Client {
	return sl.Redis
}

// IsExist 是否存在
func (sl *_setList) IsExist(id any, key string) (bool, error) {
	sl.RWL.RLock()
	result, err := sl.Redis.SIsMember(context.Background(), sl.TopicKey(id), key).Result()
	sl.RWL.RUnlock()
	return result, err
}

func (sl *_setList) Add(id any, value string) error {
	sl.RWL.Lock()
	err := sl.Redis.SAdd(context.Background(), sl.TopicKey(id), value).Err()
	sl.RWL.Unlock()
	return err
}

// Adds 添加多个key
func (sl *_setList) Adds(id any, keys []string) error {
	sl.RWL.Lock()
	var temp []any
	for _, d := range keys {
		temp = append(temp, d)
	}
	err := sl.Redis.SAdd(context.Background(), sl.TopicKey(id), temp...).Err()
	sl.RWL.Unlock()
	return err
}

// Del 删除指定的key
func (sl *_setList) Del(id any, key string) error {
	sl.RWL.Lock()
	err := sl.Redis.SRem(context.Background(), sl.TopicKey(id), key).Err()
	sl.RWL.Unlock()
	return err
}

// Dels 删除指定的keys
func (sl *_setList) Dels(id any, keys []string) error {
	sl.RWL.Lock()
	var temp []any
	for _, d := range keys {
		temp = append(temp, d)
	}
	err := sl.Redis.SRem(context.Background(), sl.TopicKey(id), temp...).Err()
	sl.RWL.Unlock()
	return err
}

// Spop 获取并删除limit个key
func (sl *_setList) Spop(id any, limit uint) ([]string, error) {
	sl.RWL.Lock()
	result, err := sl.Redis.SPopN(context.Background(), sl.TopicKey(id), int64(limit)).Result()
	sl.RWL.Unlock()
	return result, err
}

// SpopAll 获取并删除limit个key
func (sl *_setList) SpopAll(id any) ([]string, error) {
	sl.RWL.Lock()
	//1、获取所有成员列表
	result, err := sl.Redis.SMembers(context.Background(), sl.TopicKey(id)).Result()
	if err == nil {
		//2、获取成员列表成功后，直接删除键
		err = sl.Redis.Del(context.Background(), sl.TopicKey(id)).Err()
	}
	sl.RWL.Unlock()
	return result, err
}

// GetRandKeys 随机获取limit个key
func (sl *_setList) GetRandKeys(id any, limit uint) ([]string, error) {
	sl.RWL.RLock()
	result, err := sl.Redis.SRandMemberN(context.Background(), sl.TopicKey(id), int64(limit)).Result()
	sl.RWL.RUnlock()
	return result, err
}

// Count 获取集合的成员数量
func (sl *_setList) Count(id any) (int64, error) {
	sl.RWL.RLock()
	defer sl.RWL.RUnlock()
	result, err := sl.Redis.SCard(context.Background(), sl.TopicKey(id)).Result()
	if err == nil || err == redis.Nil {
		return result, nil
	}
	return result, err
}

// GetAllKey 获取所有的key
func (sl *_setList) GetAllKey(id any) ([]string, error) {
	sl.RWL.RLock()
	result, err := sl.Redis.SMembers(context.Background(), sl.TopicKey(id)).Result()
	sl.RWL.RUnlock()
	return result, err
}

// ClearAll 清空所有的记录（直接删除key）
func (sl *_setList) ClearAll(id any) error {
	sl.RWL.Lock()
	err := sl.Redis.Del(context.Background(), sl.TopicKey(id)).Err()
	sl.RWL.Unlock()
	return err
}
